unit cuSplitFile;

interface

uses Classes, cuSplitLine;

(*
TSplitLine

Will load a file and remove any blank/comment lines, and cycles lines/words with nextword()/nextline() command.

Example:

  unit SplitFileTest;

  uses ucSplitFile;

  var
    SplitFile : TSplitFile;

  begin
    InternalSeperator : char;
    GroupingChar      : char;

    SplitFile := TSplitter.Create;

    if ( SplitFile.LoadFile( FileName ) ) then
    begin
      while SplitFile.GetNextLine() do
        if (SplitFile.To_Str(0) = 'TYRE') then
          TyreList.Add( SplitFile.To_Int(1) );
    end;
  end;

*)
type
  TSplitFile = class( TSplitLine ) //Extension of TSplitLine
  private
    m_Lines         : TStringList;
    m_LineIndex     : integer;
    m_Line          : string;
    m_CommentIdent  : string;
  public
    constructor Create;
    destructor Destroy; override;
    procedure clearLists;
    function loadFile(nFileName:string):boolean; //Returns true if successful
    function saveFile(nFileName:string):boolean;
    function importLines(var nLines:TStringList;const overwriteLines:boolean=TRUE):boolean;
    function exportLines(var nLines:TStringList):boolean;
    procedure newLine( nLine:string ); //If no more lines, will return FALSE to end the loop, will auto-split the line once this is called.

    function removeJunkLines(const newLines:TStringList):TStringList; //Removes "Blank Lines" and Comment Lines. Error: Array changes size once line deleted, so loop is wrong size at the end.
    function getNextLine():boolean; //If no more lines, will return FALSE to end the loop, will auto-split the line once this is called.
    function saveTillIndex(Index:string):TStringList; //If no more lines, will return FALSE to end the loop, will auto-split the line once this is called.

    property Line      : string read m_Line;
    property LineIndex : integer read m_LineIndex;
  end;

implementation

{=====================================================}
uses SysUtils, cuFuncs, Dialogs;

    {==============================================================}
    {  TSplitLine                                                  }
    {==============================================================}

constructor TSplitFile.Create;
begin
  inherited Create;

  m_Lines      := TStringList.Create;
  m_LineIndex  := -1;
  m_Line       := '';
  m_CommentIdent := '!';
end;

destructor TSplitFile.Destroy;
begin
  FreeAndNil( m_Lines );

  inherited Destroy;
end;

procedure TSplitFile.clearLists();
begin
  inherited clearLists();

  m_Lines.Clear;
  m_LineIndex  := -1;
  m_Line       := '';
  m_CommentIdent := '!';
end;

function TSplitFile.loadFile(nFileName:string):boolean;
begin
  clearLists();

  result := TRUE;

  if (not FileExists(nFileName)) then
  begin
    result := FALSE;
    addError('!WARNING! Missing File >> '+nFileName);
    exit;  // Will return false, for failed loading.
  end;

  m_Lines.LoadFromFile(nFileName);

  m_Lines := removeJunkLines( m_Lines ); //Removes blank/comment lines.
end;

function TSplitFile.saveFile(nFileName:string):boolean;
begin
  m_Lines.SaveToFile(nFileName);
  result := TRUE;
end;

function TSplitFile.importLines(var nLines:TStringList;const overwriteLines:boolean=TRUE):boolean; // can import a stringlist
begin
  if (overwriteLines) then
    clearLists();

  if (nLines.Count > 0) then result := TRUE
  else                       result := FALSE;

  if (result)  then
    m_Lines := removeJunkLines( nLines ); //Removes blank/comment lines, not working atm.
end;

function TSplitFile.exportLines(var nLines:TStringList):boolean; //Fills up a TStringList with whats in the m_Lines list.
begin
  nLines := m_Lines;
  result := TRUE;
end;

function TSplitFile.removeJunkLines(const newLines:TStringList):TStringList; //Removes "Blank Lines" and Comment Lines. Error: Array changes size once line deleted, so loop is wrong size at the end.
var L : integer;
begin
  result := TStringList.Create();

  for L := 0 to newLines.Count-1 do
  begin
    if (Length(m_Lines.Strings[L]) > 0)and(m_Lines.Strings[L][1] <> m_CommentIdent) then
      result.Add(m_Lines.Strings[L]);
  end;

{  L := -1;
  while (L < m_Lines.Count-1) do
  begin
    Inc( L );
    if (Length(m_Lines.Strings[L]) = 0)or(m_Lines.Strings[L][1] = m_CommentIdent) then //Will ignore comments and blank lines... I hope...
    begin
//      addError('!DEBUG! Removing Line - '+IntToStr(L)+'/'+IntToStr(m_Lines.Count)+' > '+m_Lines.Strings[L]);

      m_Lines.Delete(L);

      Dec( L ); // Removed Line so need to step back one.
    end;
  end;
}
end;

function TSplitFile.getNextLine():boolean;
begin
  result := FALSE;

  if (m_LineIndex >= m_Lines.Count-1) then // End of File
  begin
    addError('!DEBUG! End of Lines : '+IntToStr(m_Lines.Count));
    m_LineIndex := -1;
    exit; //No more lines to do...
  end;

  result := TRUE;

  Inc( m_LineIndex );

  m_Line := m_Lines[ m_LineIndex ];

  explodeString( m_Line );
end;

function TSplitFile.saveTillIndex( Index:string ):TStringList; //If no more lines, will return FALSE to end the loop, will auto-split the line once this is called.
begin
  result := TStringList.Create();

  if (GetNextLine() = FALSE) then Exit;

  repeat
    result.Add( m_Line );
  until (GetNextLine() = FALSE)or(m_Line = Index);
end;

procedure TSplitFile.newLine( nLine:string ); //If no more lines, will return FALSE to end the loop, will auto-split the line once this is called.
begin
  m_Lines.Add( nLine );
end;

end.
